/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain (a) copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.kizitonwose.calendarview.fraction;

import ohos.aafwk.content.Intent;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.BaseItemProvider;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.ListContainer;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.window.dialog.ToastDialog;

import com.kizitonwose.calendarview.CalendarView;
import com.kizitonwose.calendarview.EasyDialog;
import com.kizitonwose.calendarview.QuickBaseItemProvider;
import com.kizitonwose.calendarview.ResourceTable;
import com.kizitonwose.calendarview.model.CalendarDay;
import com.kizitonwose.calendarview.model.CalendarMonth;
import com.kizitonwose.calendarview.model.enums.DayOwner;
import com.kizitonwose.calendarview.ui.ViewContainer;
import com.kizitonwose.calendarview.uinterface.DayBinder;
import com.kizitonwose.calendarview.uinterface.MonthHeaderFooterBinder;
import com.kizitonwose.calendarview.uinterface.MonthScrollListener;
import com.kizitonwose.calendarview.utils.DayExtensions;
import com.kizitonwose.calendarview.utils.DisplayUtils;
import com.kizitonwose.calendarview.utils.ListExtension;
import com.kizitonwose.calendarview.utils.StringExtension;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @version 1.0
 * @date 2021/2/24 10:42
 */
public class Example3Fraction extends BaseFraction {
    private ListContainer exThreeRv;
    private CalendarView exThreeCalendar;
    private LocalDate selectedDate;
    private LocalDate today = LocalDate.now();
    private DateTimeFormatter titleSameYearFormatter = DateTimeFormatter.ofPattern("MMMM");
    private DateTimeFormatter titleFormatter = DateTimeFormatter.ofPattern("MMM yyyy");
    private DateTimeFormatter selectionFormatter = DateTimeFormatter.ofPattern("d MMM yyyy");
    private Text title;
    private Map<LocalDate, List<Event>> events = new HashMap<>();
    private List<Event> data = new ArrayList<>();
    private BaseItemProvider itemProvider;
    private Text exThreeSelectedDateText;
    private Image exThreeAddButton;

    @Override
    protected int getLayoutResId() {
        return ResourceTable.Layout_example_3_fraction;
    }

    @Override
    protected int getStatusBarColor() {
        return mContext.getColor(ResourceTable.Color_example_3_statusbar_color);
    }

    @Override
    protected void initComponent(Component content, ComponentContainer container, Intent intent) {
        title = findComponentById(ResourceTable.Id_title);
        exThreeCalendar = findComponentById(ResourceTable.Id_exThreeCalendar);
        exThreeSelectedDateText = findComponentById(ResourceTable.Id_exThreeSelectedDateText);
        exThreeAddButton = findComponentById(ResourceTable.Id_exThreeAddButton);
        exThreeRv = findComponentById(ResourceTable.Id_exThreeRv);
        exThreeRv.setOrientation(Component.VERTICAL);
        exThreeRv.setItemProvider(itemProvider = new QuickBaseItemProvider<Event>(mContext,data) {
            @Override
            protected int getComponentResourceLayout(ComponentContainer componentContainer, int componentType) {
                return ResourceTable.Layout_example_3_event_item_view;
            }

            @Override
            protected void bindComponentHolder(BaseComponentHolder holder, int position, int componentType) {
                holder.setText(ResourceTable.Id_itemEventText, getItem(position).text);
            }
        });
        exThreeRv.setItemClickedListener(new ListContainer.ItemClickedListener() {
            @Override
            public void onItemClicked(ListContainer listContainer, Component component, int position, long var4) {
                int margin = AttrHelper.vp2px(40, AttrHelper.getDensity(mContext));
                EasyDialog.getInstance(mContext)
                        .setContentResId(ResourceTable.Layout_example_3_delete_dialog)
                        .setSize((int) DisplayUtils.getWidth(mContext) - margin, ComponentContainer.LayoutConfig.MATCH_CONTENT)
                        .setClickListener(ResourceTable.Id_save, new EasyDialog.ClickedListener() {
                            @Override
                            public void onClick(EasyDialog dialog) {
                                deleteEvent(data.get(position));
                                dialog.destroy();
                            }
                        }).setClickListener(ResourceTable.Id_close, new EasyDialog.ClickedListener() {
                    @Override
                    public void onClick(EasyDialog dialog) {
                        dialog.destroy();
                    }
                }).show();

            }
        });

        findComponentById(ResourceTable.Id_iBack).setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                backFraction();
            }
        });
        DayOfWeek[] daysOfWeek = DayExtensions.daysOfWeekFromLocale();
        YearMonth currentMonth = YearMonth.now();
        exThreeCalendar.setup(currentMonth, currentMonth.plusMonths(10), daysOfWeek[0]);
        exThreeCalendar.scrollToMonth(currentMonth);
        exThreeCalendar.setDayBinder(new DayBinder<DayViewContainer>() {
            @Override
            public DayViewContainer create(Component component) {
                return new DayViewContainer(component);
            }

            @Override
            public void bind(DayViewContainer container, CalendarDay day) {
                try {
                    container.day = day;
                    Text textView = container.textView;
                    Component dotView = container.dotView;
                    textView.setText(String.valueOf(day.getDate().getDayOfMonth()));

                    if (day.getOwner() == DayOwner.THIS_MONTH) {
                        textView.setVisibility(Component.VISIBLE);
                        if (day.getDate().isEqual(today)) {
                            textView.setTextColor(new Color(mContext.getResourceManager().getElement(ResourceTable.Color_example_3_white).getColor()));
                            ShapeElement element = new ShapeElement(mContext, ResourceTable.Graphic_example_3_today_bg);
                            textView.setBackground(element);
                            dotView.setVisibility(Component.INVISIBLE);
                        } else if (selectedDate != null && day.getDate().isEqual(selectedDate)) {
                            textView.setTextColor(new Color(mContext.getResourceManager().getElement(ResourceTable.Color_example_3_blue).getColor()));
                            ShapeElement element = new ShapeElement(mContext, ResourceTable.Graphic_example_3_selected_bg);
                            textView.setBackground(element);
                            dotView.setVisibility(Component.INVISIBLE);
                        } else {
                            textView.setTextColor(new Color(mContext.getResourceManager().getElement(ResourceTable.Color_example_3_black).getColor()));
                            textView.setBackground(null);
                            boolean empty = ListExtension.getInstance(events.get(day.getDate())).orEmpty().getList().isEmpty();
                            dotView.setVisibility(!empty ? Component.VISIBLE : Component.HIDE);
                        }
                    } else {
                        textView.setVisibility(Component.INVISIBLE);
                        dotView.setVisibility(Component.INVISIBLE);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        exThreeCalendar.setMonthScrollListener(new MonthScrollListener() {
            @Override
            public void onMonthScroll(CalendarMonth calendarMonth) {
                if (calendarMonth.getYear() == today.getYear()) {
                    title.setText(titleSameYearFormatter.format(calendarMonth.getYearMonth()));
                } else {
                    title.setText(titleFormatter.format(calendarMonth.getYearMonth()));
                }
                // Select the first day of the month when
                // we scroll to a new month.
                LocalDate selectDate = calendarMonth.getMonth() == currentMonth.getMonth().getValue() ? today : calendarMonth.getYearMonth().atDay(1);
                selectDate(selectDate);
            }
        });
        exThreeCalendar.setMonthHeaderBinder(new MonthHeaderFooterBinder<MonthViewContainer>() {
            @Override
            public MonthViewContainer create(Component component) {
                return new MonthViewContainer(component);
            }

            @Override
            public void bind(MonthViewContainer container, CalendarMonth month) {
                // Setup each header day text if we have not done that already.
                if (container.legendLayout.getTag() == null) {
                    container.legendLayout.setTag(month.getYearMonth());

                    int childCount = container.legendLayout.getChildCount();
                    for (int i = 0; i < childCount; i++) {
                        Text text = (Text) container.legendLayout.getComponentAt(i);
                        text.setText(String.valueOf(daysOfWeek[i].name().charAt(0)));
                        try {
                            text.setTextColor(new Color(mContext.getResourceManager().getElement(ResourceTable.Color_example_3_black).getColor()));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
        exThreeAddButton.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                int margin = AttrHelper.vp2px(40, AttrHelper.getDensity(mContext));
                EasyDialog.getInstance(mContext)
                        .setContentResId(ResourceTable.Layout_example_3_input_dialog)
                        .setSize((int) DisplayUtils.getWidth(mContext) - margin, ComponentContainer.LayoutConfig.MATCH_CONTENT)
                        .setClickListener(ResourceTable.Id_save, new EasyDialog.ClickedListener() {
                            @Override
                            public void onClick(EasyDialog dialog) {
                                saveEvent(dialog.getText(ResourceTable.Id_tf).getText());
                                dialog.destroy();
                            }
                        }).setClickListener(ResourceTable.Id_close, new EasyDialog.ClickedListener() {
                    @Override
                    public void onClick(EasyDialog dialog) {
                        dialog.destroy();
                    }
                }).registerDisplayListener(new EasyDialog.DisplayListener() {
                    @Override
                    public void onDisplay(EasyDialog dialog) {
                        dialog.getTextField(ResourceTable.Id_tf).requestFocus();
                    }
                }).show();

            }
        });
    /*    mContext.getUITaskDispatcher().asyncDispatch(new Runnable() {
            @Override
            public void run() {
                selectDate(today);
            }
        });*/
    }


    class DayViewContainer extends ViewContainer {
        CalendarDay day;
        Text textView;
        Component dotView;

        public DayViewContainer(Component component) {
            super(component);
            textView = (Text) component.findComponentById(ResourceTable.Id_exThreeDayText);
            dotView = component.findComponentById(ResourceTable.Id_exThreeDotView);
            component.setClickedListener(new Component.ClickedListener() {
                @Override
                public void onClick(Component component) {
                    if (day.getOwner() == DayOwner.THIS_MONTH) {
                        selectDate(day.getDate());
                    }
                }

            });

        }
    }

    class MonthViewContainer extends ViewContainer {
        ComponentContainer legendLayout;

        public MonthViewContainer(Component component) {
            super(component);
            legendLayout = (ComponentContainer) component.findComponentById(ResourceTable.Id_legendLayout);
        }
    }

    private void selectDate(LocalDate date) {
        if (selectedDate != date) {
            LocalDate oldDate = selectedDate;
            selectedDate = date;
            if (oldDate != null) {
                exThreeCalendar.notifyDateChanged(oldDate);
            }
            exThreeCalendar.notifyDateChanged(date);
            updateAdapterForDate(date);
        }
    }

    private void saveEvent(String text) {
        try {
            if (StringExtension.getInstance(text).isBlank()) {
                new ToastDialog(mContext).setContentCustomComponent(LayoutScatter.getInstance(mContext).parse(ResourceTable.Layout_example_3_toast, null, false))
                        .setSize(ComponentContainer.LayoutConfig.MATCH_CONTENT, ComponentContainer.LayoutConfig.MATCH_CONTENT).show();
            } else {
                if (selectedDate != null) {
                    List<Event> values = ListExtension.getInstance(this.events.get(selectedDate)).orEmpty().plus(new Event(UUID.randomUUID().toString(), text, selectedDate)).getList();
                    this.events.put(selectedDate, values);
                    updateAdapterForDate(selectedDate);
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void deleteEvent(Event event) {
        LocalDate date = event.date;
        List<Event> value = this.events.get(date);
        if (value == null) {
            value = new ArrayList<>();
        }
        value.remove(event);
        events.put(date, value);
        updateAdapterForDate(date);
    }

    private void updateAdapterForDate(LocalDate date) {
        data.clear();
        List<Event> list = this.events.get(date);
        if (list == null) {
            list = new ArrayList<>();
        }
        data.addAll(list);
        itemProvider.notifyDataChanged();
        exThreeSelectedDateText.setText(selectionFormatter.format(date));
    }

    class Event {
        String id;
        String text;
        LocalDate date;

        public Event(String id, String text, LocalDate date) {
            this.id = id;
            this.text = text;
            this.date = date;
        }
    }
}
